package com.mitlab.dev.draw.util;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import com.mitlab.dev.draw.bean.ClassBean;
import com.mitlab.dev.draw.bean.ClassMethod;
import com.mitlab.dev.draw.bean.ClassParam;
import com.mitlab.dev.draw.bean.TypeParam;
import com.sun.xml.internal.bind.v2.TODO;

/**
 * <P>Description: TODO</P>
 * @ClassName: ClassUtil
 * @author G.X  2016年8月9日 下午3:01:09
 * @see TODO
 */
public class ClassUtils {

	public static void main(String[] args) throws Exception {
		String packageName = "com.mitlab.dev.draw.samleClass";
	/*	Set<String> classNames = getClassName(packageName, true);
		List<ClassBean> lists=getClassBean(classNames);*/
//		Class<?> clazz=Class.forName("com.mitlab.dev.draw.samleClass.BusiBaseReqBO");
		Class<?> clazz=Class.forName("com.mitlab.dev.draw.samleClass.ReqQryNumPoolByTypeBO");
		getClassField(clazz);
		
	}
	/**
	 * 获取类，方法，参数信息
	 * @param classNames
	 * @return
	 */
	public static List<ClassBean> getClassBean(Set<String> classNames){
		List<ClassBean> classBeanList=new ArrayList<ClassBean>();
		for(String className:classNames){
			ClassBean classBean=new ClassBean();
			//设置className
			classBean.setClassName(className);
			List<ClassMethod> methodsList=new ArrayList<ClassMethod>();
			Class<?> clazz=null;
			try {
				clazz=Class.forName(className);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			Method []methods=clazz.getDeclaredMethods();
			for(Method m:methods){
				ClassMethod cm=new ClassMethod();
				List<ClassParam> params=new ArrayList<ClassParam>();
				cm.setName(m.getName());
				//方法参数类型
				Class<?> [] pars=m.getParameterTypes();
				for(Class<?> clas:pars){
					ClassParam cp=new ClassParam();
					cp.setName(getClassField(clas));
					cp.setType(clas.toString());
					params.add(cp);
				}
				//返回参数及类型
				Class<?> returnType=m.getReturnType();
				List<ClassParam> retrunParams=new ArrayList<ClassParam>();
				ClassParam cpM=new ClassParam();
				cpM.setType(returnType.getName());
				
				cpM.setName(getClassField(returnType));
				retrunParams.add(cpM);
				cm.setResult(retrunParams);
				cm.setInputparams(params);
				methodsList.add(cm);
			}
			classBean.setMethod(methodsList);
			classBeanList.add(classBean);
		}
		return classBeanList;
	}
	/**
	 * 获取类，方法，参数信息
	 * @param classNames
	 * @return
	 */
	public static List<TypeParam> getClassField(Class<?> clazz){

		List<TypeParam> list=new ArrayList<TypeParam>();
		if(clazz==List.class){
			TypeParam tp=new TypeParam();
			tp.setName("List");
			tp.setType("List");
			list.add(tp);
		}
		Field [] fields=clazz.getDeclaredFields();
	
		for(Field f:fields){
			TypeParam tp=new TypeParam();
			tp.setName(f.getName());
			tp.setType(f.getType().toString());
			list.add(tp);
		}
//		System.out.println(clazz+"子类变量count:"+list.size());
		//查询父类属性
		Class<?> clazzF=clazz.getSuperclass();
		getClassParentField(clazzF,list);
//		System.out.println(list.size());
		return list;
	}
	/**
	 * 找到父类变量
	 */
	public static void getClassParentField(Class<?> clazz,List<TypeParam> list){
		if(clazz!=null&&!clazz.toString().equals("java.lang.Object")){
		Field [] fields=clazz.getDeclaredFields();
		for(Field f:fields){
			TypeParam tp=new TypeParam();
			tp.setName(f.getName());
			tp.setType(f.getType().toString());
			list.add(tp);
		}
		}
	}
	/**
	 * 获取某包下所有类
	 * @param packageName 包名
	 * @param isRecursion 是否遍历子包
	 * @return 类的完整名称
	 */
	public static Set<String> getClassName(String packageName, boolean isRecursion) {
		Set<String> classNames = null;
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		String packagePath = packageName.replace(".", "/");

		URL url = loader.getResource(packagePath);
		if (url != null) {
			String protocol = url.getProtocol();
			if (protocol.equals("file")) {
				classNames = getClassNameFromDir(url.getPath(), packageName, isRecursion);
			} else if (protocol.equals("jar")) {
				JarFile jarFile = null;
				try{
	                jarFile = ((JarURLConnection) url.openConnection()).getJarFile();
				} catch(Exception e){
					e.printStackTrace();
				}
				
				if(jarFile != null){
					getClassNameFromJar(jarFile.entries(), packageName, isRecursion);
				}
			}
		} else {
			/*从所有的jar包中查找包名*/
			classNames = getClassNameFromJars(((URLClassLoader)loader).getURLs(), packageName, isRecursion);
		}
		
		return classNames;
	}
	
	
	/**
	 * 从项目文件获取某包下所有类
	 * @param filePath 文件路径
	 * @param className 类名集合
	 * @param isRecursion 是否遍历子包
	 * @return 类的完整名称
	 */
	private static Set<String> getClassNameFromDir(String filePath, String packageName, boolean isRecursion) {
		Set<String> className = new HashSet<String>();
		File file = new File(filePath);
		File[] files = file.listFiles();
		for (File childFile : files) {
			if (childFile.isDirectory()) {
				if (isRecursion) {
					className.addAll(getClassNameFromDir(childFile.getPath(), packageName+"."+childFile.getName(), isRecursion));
				}
			} else {
				String fileName = childFile.getName();
				if (fileName.endsWith(".class") && !fileName.contains("$")) {
					className.add(packageName+ "." + fileName.replace(".class", ""));
				}
			}
		}

		return className;
	}
	
	
	/**
	 * @param jarEntries
	 * @param packageName
	 * @param isRecursion
	 * @return
	 */
	private static Set<String> getClassNameFromJar(Enumeration<JarEntry> jarEntries, String packageName, boolean isRecursion){
		Set<String> classNames = new HashSet<String>();
		
		while (jarEntries.hasMoreElements()) {
			JarEntry jarEntry = jarEntries.nextElement();
			if(!jarEntry.isDirectory()){
				/*
	             * 这里是为了方便，先把"/" 转成 "." 再判断 ".class" 的做法可能会有bug
	             * (FIXME: 先把"/" 转成 "." 再判断 ".class" 的做法可能会有bug)
	             */
				String entryName = jarEntry.getName().replace("/", ".");
				if (entryName.endsWith(".class") && !entryName.contains("$") && entryName.startsWith(packageName)) {
					entryName = entryName.replace(".class", "");
					if(isRecursion){
						classNames.add(entryName);
					} else if(!entryName.replace(packageName+".", "").contains(".")){
						classNames.add(entryName);
					}
				}
			}
		}
		
		return classNames;
	}
	
	
	/**
	 * 从所有jar中搜索该包，并获取该包下所有类
	 * @param urls URL集合
	 * @param packageName 包路径
	 * @param isRecursion 是否遍历子包
	 * @return 类的完整名称
	 */
	private static Set<String> getClassNameFromJars(URL[] urls, String packageName, boolean isRecursion) {
		Set<String> classNames = new HashSet<String>();
		
		for (int i = 0; i < urls.length; i++) {
			String classPath = urls[i].getPath();
			
			//不必搜索classes文件夹
			if (classPath.endsWith("classes/")) {continue;}

			JarFile jarFile = null;
			try {
				jarFile = new JarFile(classPath.substring(classPath.indexOf("/")));
			} catch (IOException e) {
				e.printStackTrace();
			}

			if (jarFile != null) {
				classNames.addAll(getClassNameFromJar(jarFile.entries(), packageName, isRecursion));
			}
		}
		
		return classNames;
	}
}
